/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package analiseSintatica.Regras.DeclaracoesIniciais;

import AnaliseLexicaFinal.EstruturaDeDados.LinkToken;
import analiseSemantica.Tipos.TipoSemantico;
import analiseSemantica.Tipos.TiposSemanticos;
import analiseSemantica.estruturadedados.Funcao;
import analiseSintatica.AnalisadorSintatico;
import analiseSintatica.ErroSintaticoException;
import analiseSintatica.Regras.Funcao.RegraArgsDeclaracao;
import analiseSintatica.Regras.Regra;
import analiseSintatica.Regras.Tipos.RegraTipo;
import java.util.LinkedList;

/**
 *
 * @author Dede do Bem
 * 
 * 
 * <prototipo> ::= <tipo> identificador "(" [<args_declaracao>] ")"
 */
public class RegraPrototipo extends Regra{



    protected static Regra instancia;
    protected String estrutura = "<tipo> identificador '(' [<args_declaracao>] ')'";


    /**
     * Construtor privado necessario ao singleton
     */
    private RegraPrototipo() {
    }

    /**
     * Retorna a unica instancia dessa classe.
     * @return
     */
    public static RegraPrototipo getInstance() {
        if (instancia == null) {
            instancia = new RegraPrototipo();
        }
        return (RegraPrototipo) instancia;
    }

    

    @Override
    public TiposSemanticos analisar(LinkedList<LinkToken> listaTokens) throws ErroSintaticoException {

    	TipoSemantico tipo = RegraTipo.getInstance().analisar(listaTokens).removeTipos(); //cria filho da sub arvore de prototipo
    	String stringtipo = (String)tipo.getTipo();
    	Funcao funcao = new Funcao(listaTokens.getFirst().getLexema());
        funcao.setRetorno(stringtipo);
        
    	reconheceToken(listaTokens, "identificador", estrutura);
        reconheceLexema(listaTokens, "delimitador", "(", estrutura);
        
        if(listaContem(RegraArgsDeclaracao.getInstance().getPrimeiro(), listaTokens.getFirst())){
        	TiposSemanticos tipos = RegraArgsDeclaracao.getInstance().analisar(listaTokens);
        	if(tipos == null){
        		reconheceLexema(listaTokens, "delimitador", ")", estrutura);
        		return null;
        	}else{
        		while (tipos.size() != 0){
            		funcao.setParamEntrada((String)tipos.removeTipos().getTipo());
            	}
        	}
        }
        reconheceLexema(listaTokens, "delimitador", ")", estrutura);
        AnalisadorSintatico.escopoatual.getParent().put(funcao.getLexema(), funcao);
        TiposSemanticos retorno = new TiposSemanticos();
        retorno.addTipos(tipo);
        return retorno;
    }
    
   

    @Override
    protected void setPrimeiro() {
        this.primeiro = RegraTipo.getInstance().getPrimeiro();
    }

    

}
